package com.hd.trans.utils;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.RequiresApi;

import com.hd.trans.files.repository.StoreRepository;
import com.hd.trans.ui.base.AppContextProvider;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.attribute.BasicFileAttributes;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by HXL on 16/8/11.
 * 管理录音文件的类
 */
public class FileUtils {

    private static final String ROOTNAME = "ve";


    //翻译文件存放地址
    private static String getTransFilePath() {
        return FileUtil.getCacheRoot() + "trans/";
    }

    //原始文件(不能播放)
    private static String getAudioPcmPath() {
        return FileUtil.getCacheRoot() + "pcm/";
    }

    //可播放的高质量音频文件
    private static String getAudioWavPath() {
        return FileUtil.getCacheRoot() + "wav/";
    }

    public static String getTransFileBasePath() {
        File file = new File(getTransFilePath());
        //创建目录
        if (!file.exists()) {
            file.mkdirs();
        }
        return getTransFilePath();
    }

    public static String getFileNameByPath(String path) {
        try {
            return new File(path).getName();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    public static String getAlbumDir() {
        return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsolutePath() + File.separator + "translator";
    }

    public static String getPcmFileAbsolutePath(String fileName) {
        if (TextUtils.isEmpty(fileName)) {
            throw new NullPointerException("fileName isEmpty");
        }
        if (!isSdcardExit()) {
            throw new IllegalStateException("sd card no found");
        }
        String mAudioRawPath = "";
        if (isSdcardExit()) {
            if (!fileName.endsWith(".pcm")) {
                fileName = fileName + ".pcm";
            }
//            String fileBasePath = Environment.getExternalStorageDirectory().getAbsolutePath() + getAudioPcmPath();
            String fileBasePath = getAudioPcmPath();
            File file = new File(fileBasePath);
            //创建目录
            if (!file.exists()) {
                file.mkdirs();
            }
            mAudioRawPath = fileBasePath + fileName;
        }

        return mAudioRawPath;
    }
    /**
     * 获取存储目录
     *
     * @return
     */
    public static String getAudioPath() {
        return getAudioWavPath();
    }

    public static void initialize(Context context, File path) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && null != path) {
            do {
                File checkRootPath = context.getExternalFilesDir("test");
                if (checkRootPath != null) {
                    checkRootPath = checkRootPath.getParentFile();
                    if (checkRootPath != null && path.getAbsolutePath().startsWith(checkRootPath.getAbsolutePath())) {
                        //如果扩展路径
                        break;
                    }
                }
                int hasReadPermission = context.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
                if (hasReadPermission != PackageManager.PERMISSION_GRANTED) {
                    throw new IllegalAccessError("Can`t get WRITE_EXTERNAL_STORAGE permission. " + path.getAbsolutePath());
                }
            } while (false);
        }
        if (null == path) {
            path = context.getExternalFilesDir(ROOTNAME);
        }

        checkPath(path, false);

        path = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC), ROOTNAME + "/");
        checkPath(path, true);
        checkPath(path, false);

    }


    public static String getWavFileAbsolutePath(String fileName) {
        if (fileName == null) {
            throw new NullPointerException("fileName can't be null");
        }
        if (!isSdcardExit()) {
            throw new IllegalStateException("sd card no found");
        }

        String mAudioWavPath = "";
        if (isSdcardExit()) {
            if (!fileName.endsWith(".wav")) {
                fileName = fileName + ".wav";
            }
//            String fileBasePath = Environment.getExternalStorageDirectory().getAbsolutePath() + getAudioWavPath();
            String fileBasePath = getAudioWavPath();
            File file = new File(fileBasePath);
            //创建目录
            if (!file.exists()) {
                file.mkdirs();
            }
            mAudioWavPath = fileBasePath + fileName;
        }
        return mAudioWavPath;
    }

    /**
     * 判断是否有外部存储设备sdcard
     *
     * @return true | false
     */
    public static boolean isSdcardExit() {
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
            return true;
        else
            return false;
    }

    /**
     * 获取全部pcm文件列表
     *
     * @return
     */
    public static List<File> getPcmFiles() {
        List<File> list = new ArrayList<>();
//        String fileBasePath = Environment.getExternalStorageDirectory().getAbsolutePath() + getAudioPcmPath();
        String fileBasePath = getAudioPcmPath();

        File rootFile = new File(fileBasePath);
        if (!rootFile.exists()) {
        } else {

            File[] files = rootFile.listFiles();
            for (File file : files) {
                list.add(file);
            }

        }
        return list;

    }

    /**
     * 获取全部wav文件列表
     *
     * @return
     */
    public static List<File> getWavFiles() {
        List<File> list = new ArrayList<>();
//        String fileBasePath = Environment.getExternalStorageDirectory().getAbsolutePath() + getAudioWavPath();
        String fileBasePath = getAudioWavPath();

        File rootFile = new File(fileBasePath);
        if (!rootFile.exists()) {
        } else {
            File[] files = rootFile.listFiles();
            for (File file : files) {
                list.add(file);
            }

        }
        return list;
    }

    /**
     * 删除方法 这里只会删除某个文件夹下的文件，如果传入的directory是个文件，将不做处理
     *
     * @param directory
     */
    public static void deleteFilesByDirectory(File directory) {
        if (directory != null && directory.exists() && directory.isDirectory()) {
            for (File child : directory.listFiles()) {
                if (child.isDirectory()) {
                    deleteFilesByDirectory(child);
                }
                child.delete();
            }
        }
    }


    public static void deleteAllTtsFiles() {
        if (!isSdcardExit()) {
            return;
        }
//        String dirPath = Environment.getExternalStorageDirectory().getAbsolutePath() + getAudioWavPath();
        String dirPath = getAudioWavPath();
        File dirFile = new File(dirPath);
        if (!dirFile.exists()) {
            return;
        }
        deleteFilesByDirectory(dirFile);

    }

    /**
     * 删除文件
     *
     * @param file
     * @return
     */
    public static boolean safeDelete(File file) {
        try {
            if (file != null && file.exists()) {
                return deleteFileByNio(file);
            }
        } catch (Exception e) {
            // 文件权限未授予
        }
        return false;
    }

    /**
     * 清理文件夹,文件夹不存在，新建该文件夹。   文件夹存在，则删除所有子文件
     *
     * @param file
     */
    public static void clearFolderSubFiles(File file) {
        if (!file.exists()) {
            file.mkdirs();
        } else {
            if (file.isDirectory()) {
                File[] files = file.listFiles();
                if (files != null) {
                    for (File cache : files) {
                        safeDelete(cache);
                    }
                }
            }
        }
    }

    /**
     * Path就是取代File的
     * 使用java最小nio文件库删除文件
     *
     * @param file
     */
    public static boolean deleteFileByNio(File file) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            try {
                Files.delete(file.toPath());
            } catch (Exception e) {
                return false;
            }
        } else {
            return file.delete();
        }
        return true;
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    public static long getAccessTime(String path) {
        BasicFileAttributes bAttributes = null;
        File file = new File(path);
        long accessTime = 0;
        try {
            bAttributes = Files.readAttributes(file.toPath(),
                    BasicFileAttributes.class);
            accessTime = bAttributes.lastAccessTime().toMillis();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return accessTime;
    }


    /**
     * 判断文件是否存在
     *
     * @param path true 存在 false 不存在
     */
    public static boolean checkFileExists(String path) {
        File file = new File(path);
        return file.isFile() && file.exists();

    }


    /**
     * 判断文件是否存在
     *
     * @param path 文件的路径
     * @return
     */
    public static boolean isExists(String path) {
        File file = new File(path);
        return file.exists();
    }

    /**
     * 检查path，如不存在创建之<br>
     * 并检查此路径是否存在文件.nomedia,如没有创建之
     *
     * @param excludeNoMediaFile 是否需要检查排除.nomedia文件
     */
    public static void checkPath(File path, boolean excludeNoMediaFile) {
        if (!path.exists())
            path.mkdirs();
        File fNoMedia = new File(path, ".nomedia");
        if (excludeNoMediaFile) {
            if (fNoMedia.exists()) {
                fNoMedia.delete();
            }
        } else {
            if (!fNoMedia.exists()) {
                try {
                    fNoMedia.createNewFile();
                } catch (IOException ignored) {
                }
            }
        }
    }


    /**
     * 获取存储目录
     *
     * @return
     */


    /**
     * 移动文件
     *
     * @param srcFileName 源文件完整路径
     * @param destDirName 目的目录完整路径
     * @return 文件移动成功返回true，否则返回false
     */
    public static boolean moveFile(String srcFileName, String destDirName) {

        File srcFile = new File(srcFileName);
        if (!srcFile.exists() || !srcFile.isFile())
            return false;

        File destDir = new File(destDirName);
        if (!destDir.exists())
            destDir.mkdirs();

        return srcFile.renameTo(new File(destDirName + File.separator
                + srcFile.getName()));
    }


    /**
     * 使用ffmpeg命令行进行抽取音频
     *
     * @param srcFile    原文件
     * @param targetFile 目标文件
     * @return 抽取后的音频文件
     */
    public static String[] extractAudio(String srcFile, String targetFile) {
        //-vn:video not
        String mixAudioCmd = "ffmpeg -i %s -acodec copy -vn %s";
        mixAudioCmd = String.format(mixAudioCmd, srcFile, targetFile);
        return mixAudioCmd.split(" ");
    }

    /**
     * 删除单个文件
     *
     * @param sPath 被删除文件的文件名
     * @return 单个文件删除成功返回true，否则返回false
     */
    public static boolean deleteFile(String sPath) {
        boolean is;
        File file = new File(sPath);
        // 路径为文件且不为空则进行删除
        if (file.isFile() && file.exists()) {
            file.delete();
            is = true;
        } else {
            is = false;
        }
        return is;
    }


    /**
     * 复制文件
     *
     * @param fromFile 要复制的文件目录
     * @param toFile   要粘贴的文件目录
     * @return 是否复制成功
     */
    public static boolean copyFile(Context context, String fromFile, String toFile) {
        //要复制的文件目录
        File root = new File(fromFile);
        //如同判断SD卡是否存在或者文件是否存在
        //如果不存在则 return出去
        if (!root.exists()) {
            return false;
        }

        //目标目录
        File targetDir = new File(toFile);
        //创建目录
        if (!targetDir.exists()) {
            try {
                targetDir.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return copySdcardFile(context, fromFile, toFile);
    }


    /**
     * 文件拷贝
     * 要复制的目录下的所有非子目录(文件夹)文件拷贝
     *
     * @param fromFile
     * @param toFile
     * @return
     */

    public static boolean copySdcardFile(Context context, String fromFile, String toFile) {

        try {
            FileInputStream fosfrom = new FileInputStream(fromFile);
            FileOutputStream fosto = new FileOutputStream(toFile);
            byte bt[] = new byte[1024];
            int c;
            while ((c = fosfrom.read(bt)) > 0) {
                fosto.write(bt, 0, c);
            }
            fosfrom.close();
            fosto.close();
//            boolean store = AudioUtils.storeMusicInfo(context, toFile, null);
            StoreRepository storeRepository = new StoreRepository();
            storeRepository.storeAudio(context, toFile);
            deleteFile(toFile);
            return true;

        } catch (Exception ex) {
            return false;
        }
    }

    /**
     * 判断文件是否存在
     *
     * @param path true 存在 false 不存在
     * @return
     */
    public static boolean query(String path) {
        File file = new File(path);
        return file.isFile() && file.exists();
    }


    /**
     * oldPath 和 newPath必须是新旧文件的绝对路径
     */
    private static File renameFile(String oldPath, String newPath) {
        if (TextUtils.isEmpty(oldPath)) {
            return null;
        }
        if (TextUtils.isEmpty(newPath)) {
            return null;
        }
        File oldFile = new File(oldPath);
        File newFile = new File(newPath);
        boolean b = oldFile.renameTo(newFile);
        File file2 = new File(newPath);
        return file2;
    }

    /**
     * 获取存储目录
     *
     * @return
     */
    public static String getStorageDirectory() {
        return FileUtil.getCacheRoot();
    }

    /****
     * 计算文件大小
     *
     * @param length
     * @return
     */
    public static String ShowLongFileSzie(Long length) {
        if (length >= 1048576) {
            return (length / 1048576) + "MB";
        } else if (length >= 1024) {
            return (length / 1024) + "KB";
        } else if (length < 1024) {
            return length + "B";
        } else {
            return "0KB";
        }
    }


    //获取状态栏高度
    public static int getStatusBarHeight(Context context) {
        //先获取资源id，根据id获取资源
        Resources resources = context.getResources();
        int statusBarHeightId = resources.getIdentifier("status_bar_height", "dimen", "android");
        return resources.getDimensionPixelOffset(statusBarHeightId);
    }

    /**
     * 通过Uri，获取录音文件的路径（绝对路径）
     *
     * @param uri 录音文件的uri
     * @return 录音文件的路径（String）
     */

    private static String getAudioFilePathFromUri(Context context, Uri uri) {
        String temp = null;
        Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
//        cursor.moveToFirst();
        if (cursor != null) {
            while (cursor.moveToNext()) {
                int index = cursor.getColumnIndex(MediaStore.Audio.AudioColumns.DATA);
                temp = cursor.getString(index);
                cursor.close();

            }
        }

        return temp;

    }


    public static String getSDFilePath() {
        // Environment.getExternalStorageDirectory().getAbsolutePath()
        File file = Environment.getExternalStorageDirectory();
        File folder;
        String brand = Build.BRAND.toUpperCase();//获取手机厂商转大写
        switch (brand) {
            case "HUAWEI":
                folder = new File(file, "Sounds");
                break;
            case "HONOR":
                folder = new File(file, "Recordings");
                break;
            case "XIAOMI":
                folder = new File(file, "MIUI/sound_recorder");
                break;
            case "VIVO":
                folder = new File(file, "Record");
                if (!folder.exists()) {
                    ///storage/sdcard0/录音/
                    folder = new File(file, "录音/");
                }
                break;
            case "OPPO":
                folder = new File(file, "Recordings");
                break;
            case "MEIZU":
                folder = new File(file, "Recorder");
                break;
            case "SAMSUNG":
                folder = new File(file, "Sounds");
                if (!folder.exists()) {
                    ///storage/sdcard0/录音/
                    folder = new File(file, "Voice Recorder");
                }
                break;
            case "NUBIA":
                folder = new File(file, "neoRecord");
                break;
            case "ONEPLUS":
                folder = new File(file, "Record/SoundRecord");
                break;
            default:
                folder = new File(file, "Recordss");
                break;
//                return null;
//                folder = new File("", "");
        }
        return folder.getPath();
    }

    /**
     * 保存错误信息到文件中
     *
     * @param ex
     * @return  返回文件名称,便于将文件传送到服务器
     */
    public static String saveCrashInfo2File(Throwable ex) {
        StringBuffer sb = new StringBuffer();
        Writer writer = new StringWriter();
        PrintWriter printWriter = new PrintWriter(writer);
        ex.printStackTrace(printWriter);
        Throwable cause = ex.getCause();
        while (cause != null) {
            cause.printStackTrace(printWriter);
            cause = cause.getCause();
        }
        printWriter.close();
        String result = writer.toString();
        sb.append(result);
        try {
            long timestamp = System.currentTimeMillis();
            DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
            String time = formatter.format(new Date());
            String fileName = "crash-" + time + "-" + timestamp + ".log";
            String path = getErrorOutput().getAbsolutePath()+File.separator+fileName;
            File dir = new File(path);
            if (!dir.exists()) {
                dir.createNewFile();
            }
            FileOutputStream fos = new FileOutputStream(path);
            fos.write(sb.toString().getBytes());
            fos.close();
            return fileName;
        } catch (Exception e) {
            Log.e("Teemo", "an error occured while writing file...", e);
        }
        return null;
    }

    /**
     * 错误信息存储路径
     */
    public static File getErrorOutput() {
        File output = new File(AppContextProvider.getContext().getExternalFilesDir(null), "/error");
        if (!output.exists()) {
            output.mkdirs();
        }
        return output;
    }
}
